;; ============
;; Exercise 2.2
;; ============

;; Consider the problem of representing line segments in a plane. Each
;; segment is represented as a pair of points: a starting point and an
;; ending point.

;; Define a constructor make-segment and selectors start-segment and
;; end-segment that define the representation of segments in terms of
;; points.

;; Furthermore, a point can be represented as a pair of numbers: the x
;; coordinate and the y coordinate. Accordingly, specify a constructor
;; make-point and selectors x-point and y-point that define this
;; representation.

;; Finally, using your selectors and constructors, define a procedure
;; midpoint-segment that takes a line segment as argument and returns
;; its midpoint (the point whose coor- dinates are the average of the
;; coordinates of the endpoints).

;; To try your procedures, you’ll need a way to print points:
(define (print-point p)
  (newline)
  (display "(")
  (display (x-point p))
  (display ",")
  (display (y-point p))
  (display ")"))

;; A:

;; Define a constructor make-segment and selectors start-segment and
;; end-segment that define the representation of segments in terms of
;; points.

(define (make-segment point1 point2)
  (cons point1 point2))

(define (start-segment seg)
  (car seg))

(define (end-segment seg)
  (cdr seg))

;; B

;; Furthermore, a point can be represented as a pair of numbers: the x
;; coordinate and the y coordinate. Accordingly, specify a constructor
;; make-point and selectors x-point and y-point that define this
;; representation.

(define (make-point xcoord ycoord)
  (cons xcoord ycoord))

(define (x-point point)
  (car point))

(define (y-point point)
  (cdr point))

;; C

;; Finally, using your selectors and constructors, define a procedure
;; midpoint-segment that takes a line segment as argument and returns
;; its midpoint (the point whose coordinates are the average of the
;; coordinates of the endpoints).

(define (average a b)
  (/ (+ a b) 2))

(define (midpoint-segment seg)
  (let ([point1 (start-segment seg)]
        [point2 (end-segment seg)])
    (make-point (average (x-point point1) (x-point point2))
                (average (y-point point1) (y-point point2)))))

;; We will define a testable print procedure.
(define* (print-point-testable p #:optional port)
  (display
   (simple-format #f "(~a,~a)\n"
                  (x-point p) (y-point p))
   port))


;; =====
;; TESTS
;; =====
(use-modules (srfi srfi-64))

(test-begin "test-2.02")
(test-group
 "test-2.02"

 (test-assert
     (string=?
      (string-trim-both (call-with-output-string
                          (λ (port)
                            (print-point-testable
                             (midpoint-segment (make-segment (make-point 1 2)
                                                             (make-point 3 4)))
                             port)))
                        char-set:whitespace)
      "(2,3)")))

(test-end "test-2.02")
